import 'package:flutter/material.dart';

///
/// 滑动物理特性工具类
/// 提供各种滑动效果的ScrollPhysics配置
///
class ScrollPhysicsUtils {
  /// Android风格的滑动物理特性
  /// 特点：硬边界，滑动到边界时立即停止，不会出现回弹效果
  /// 适用场景：不希望有弹性效果的页面，防止滑动出现负数
  static const ScrollPhysics clampingPhysics = ClampingScrollPhysics();

  /// iOS风格的滑动物理特性
  /// 特点：有回弹效果，滑动超出边界时会回弹
  /// 适用场景：需要iOS原生体验的页面
  static const ScrollPhysics bouncingPhysics = BouncingScrollPhysics();

  /// 禁用滑动
  /// 特点：完全禁用滑动功能
  /// 适用场景：固定内容，不需要滚动的页面
  static const ScrollPhysics neverScrollablePhysics =
      NeverScrollableScrollPhysics();

  /// 自定义无负数滑动物理特性
  /// 特点：防止滑动位置出现负数，同时保持一定的用户体验
  /// 适用场景：需要精确控制滑动边界的场景
  static const ScrollPhysics noNegativePhysics = _NoNegativeScrollPhysics();

  /// 根据平台自动选择合适的滑动物理特性
  /// iOS: BouncingScrollPhysics
  /// Android: ClampingScrollPhysics
  /// 注意：需要在Widget的build方法中调用，传入context
  static ScrollPhysics getPlatformPhysics(BuildContext context) {
    return Theme.of(context).platform == TargetPlatform.iOS
        ? bouncingPhysics
        : clampingPhysics;
  }

  /// 获取防止负数滑动的物理特性
  /// 推荐用于解决"滑动不能出现负数"的问题
  static ScrollPhysics get noNegativeScrollPhysics => noNegativePhysics;

  /// 获取标准的无回弹滑动物理特性
  /// 推荐用于大多数列表和滚动页面
  static ScrollPhysics get standardPhysics => clampingPhysics;
}

///
/// 自定义滑动物理特性：防止负数滚动
///
class _NoNegativeScrollPhysics extends ScrollPhysics {
  const _NoNegativeScrollPhysics({super.parent});

  @override
  _NoNegativeScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return _NoNegativeScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) {
    // 如果尝试滚动到负数位置，则阻止滚动
    if (value < 0.0 && position.pixels <= 0.0) {
      return value;
    }

    // 如果尝试滚动超出最大范围，则阻止滚动
    if (value > 0.0 && position.pixels >= position.maxScrollExtent) {
      return value;
    }

    return 0.0;
  }

  @override
  Simulation? createBallisticSimulation(
      ScrollMetrics position, double velocity) {
    // 确保滚动位置不会小于0
    if (position.pixels <= 0.0 && velocity < 0.0) {
      return null;
    }

    // 确保滚动位置不会超出最大范围
    if (position.pixels >= position.maxScrollExtent && velocity > 0.0) {
      return null;
    }

    return super.createBallisticSimulation(position, velocity);
  }
}
